from flask import jsonify,request, Blueprint,url_for
from configs import *
from modules.Tables import *
from sqlalchemy import and_
from flask_jwt_extended import create_access_token,get_jwt_identity,jwt_required



# 创建蓝图，对应的register目录
menu_view = Blueprint('menu_view', __name__)

# 权限赋值接口
@menu_view.route('/permission_give', methods=['POST'])
@jwt_required()
@jwt_required_with_refresh
def permission_give():

    # 获取权限id 用户id  写入用户权限表 进行赋值
    user_id = request.form.get('user_id')
    permission_id = request.form.get('permission_id')

    # 去除所传数据中的首尾空格
    user_id = user_id.strip() if user_id else None
    permission_id = permission_id.strip() if permission_id else None

    if user_id is None or permission_id is None:
        return jsonify({"msg": "用户权限数据必须填写",'code':400})

    # 查询 选择用户id跟权限id 如果权限不存在 将权限赋值到用户权限表
    userper_data = db.session.query(UserPermission).filter(UserPermission.user_id==user_id).first()
    if userper_data:

        userper_data.permission_id=permission_id
        db.session.commit()

        return jsonify({'code':400,'msg':'权限修改完成'})

    print(permission_id)
    userper = UserPermission(user_id=user_id, permission_id=permission_id)
    db.session.add(userper)
    db.session.commit()

    return jsonify({'code':200,'msg':'权限赋值完成'})


# 对应权限菜单展示接口
@menu_view.route('/menu_show', methods=['GET'])
@jwt_required()
@jwt_required_with_refresh
def menu_show():

    # 获取用户id   查找该用户所拥有权限 1.超级管理员 2。普通用户
    user_id = request.args.get('user_id',None)

    # 判断用户是否存在
    if not user_id:
        return jsonify({'code':400,'msg':'用户不存在'})

    # 获取用户信息以及状态

    user_info = db.session.query(User).filter(User.id==user_id,User.user_status==1).first()

    if not user_info:
        return jsonify({'code': '400', 'message': '用户不存在'})

    # 获取用户权限数据
    permission_data = db.session.query(UserPermission.permission_id).\
        join(Permission,UserPermission.permission_id==Permission.id).filter(UserPermission.user_id==user_info.id,Permission.permission_status==1).all()

    if not permission_data:
        return jsonify({'code': '400', 'message': '用户权限不存在'})

    # 查找到用户对应权限列表，去权限菜单表里查询对应拥有该权限的菜单
    user_permission_data = [int(i['permission_id']) for i in convert_folder_to_dict_list(permission_data,['permission_id'])]


    # 获取到该用户权限标识列表 ，去权限与菜单关联表查找对应权限菜单，如果该用户有多个权限。展示多个权限的菜单，如果有并集去重
    # 查询符合条件的记录
    permission_menu_list = db.session.query(PermissionMenu).filter(
        PermissionMenu.premission_id.in_(user_permission_data)
    ).all()

    # 提取菜单标识字段并去重 (集合{}唯一去重)
    menu_ids = {item.menu_id for item in permission_menu_list}

    # 将结果转换为列表
    menu_ids_list = list(menu_ids)

    # 查找菜单表中 menu_ids_list所对应id的记录

    menu_list = convert_folder_to_dict_list(db.session.query(
        Menu.id.label('menu_id'),Menu.menu_name,
        Menu.menu_link,Menu.menu_icon,
        Menu.menu_order,Menu.menu_parent_id,
        Menu.menu_status,
    ).filter(Menu.id.in_(menu_ids_list),Menu.menu_status==1).all(),
                                            ['menu_id','menu_name','menu_link','menu_status','menu_icon','menu_order','menu_parent_id',])

    # 组装数据，把多个权限对应增删改查列表进行组合 , 查找列表内权限，查找所有权限对应菜单标识 根据menu_id 对 permissions_list进行取并集并去重！
    merge_permissions_list = merge_permissions(convert_folder_to_dict_list(db.session.query(PermissionMenu).\
        filter(PermissionMenu.premission_id.in_(list({item.premission_id for item in permission_menu_list}))).all(),
                                      ['menu_id','permissions_list']))

    # 将menu_list与 merge_permissions_list整和，判断当menu_id 相同时，两个数据合一起
    def merge_menu_permissions(menu_list, merge_permissions_list):
        """
        将 menu_list 和 merge_permissions_list 根据 menu_id 整合，
        当 menu_id 相同时，将权限信息合并到菜单项中。

        参数:
            menu_list (list): 包含菜单项的列表，每个菜单项是一个字典，至少包含 'menu_id'。
            merge_permissions_list (list): 包含权限信息的列表，每个权限项是一个字典，至少包含 'menu_id' 和权限字段。

        返回:
            list: 整合后的菜单列表，包含合并的权限信息。
        """
        merged_data = [
            {
                **menu,
                # 从 merge_permissions_list 获取权限信息
                **next((perm for perm in merge_permissions_list if perm['menu_id'] == menu['menu_id']), {})
            }
            for menu in menu_list
        ]

        return merged_data
    menu_list = merge_menu_permissions(menu_list,merge_permissions_list)

    # 自定义排序函数  按照菜单表自定义顺序来对菜单进行排序
    def custom_sort(menu):
        return menu.get('menu_order', 0)

    # 对菜单项列表进行排序
    sorted_menu_items = sorted(menu_list, key=custom_sort)

    # 从 menu_parent_id为none主节点开始找  （递归找出所有子类菜单）
    def build_tree(data, parent_id=None):
        tree = []
        for item in data:
            if item['menu_parent_id'] == parent_id:
                children = build_tree(data, item['menu_id'])
                if children:
                    item['children'] = children
                tree.append(item)
        return tree

    # 调用方法获取父子菜单组装数据
    menu_list = build_tree(sorted_menu_items)

    return jsonify({'code': 200, 'menu_list': menu_list})


# 菜单修改对应配置接口
@menu_view.route('/menu_manage_update', methods=['POST'])
@jwt_required()
@jwt_required_with_refresh
def menu_manage_update():
    """
    菜单修改对应配置接口

    参数:
        status       状态 (str): 1目录， 2菜单 （选择目录parent_id就为none值，选择菜单，展示对应路径，parent_id有值）
        parent_id    修改菜单父id (str): 要更新的菜单父id。
        menu_id      修改菜单id (str): 要更新的菜单id。
        menu_name    菜单名称 (str): 更新的菜单名称。
        menu_link    菜单路径 (str): 更新的菜单路径。
        menu_order   菜单顺序 (str): 更新的菜单顺序。
        menu_icon    菜单图标 (str): 更新的菜单图标。
    """

    # 先判断状态，当为目录或者菜单时执行不同的逻辑
    status = strip_whitespace(request.form.get('status',None))
    menu_id = strip_whitespace(request.form.get('menu_id',None))
    menu_name = strip_whitespace(request.form.get('menu_name',None))
    menu_link = strip_whitespace(request.form.get('menu_link',None))
    menu_order = strip_whitespace(request.form.get('menu_order',None))
    menu_icon = strip_whitespace(request.form.get('menu_icon',None))
    menu_parent_id = strip_whitespace(request.form.get('menu_parent_id',None))
    menu_status = strip_whitespace(request.form.get('menu_status', None))

    # 参数构建判断是否为空
    params = [status, menu_id, menu_name, menu_order]

    if not all(params):
        return jsonify({'code': 400, 'msg': '设备数据有未填写项'})

    try:
        # 查询菜单 ID 是否存在
        menu_id_data = db.session.query(Menu).filter(Menu.id == menu_id).first()
        if not menu_id_data:
            return jsonify({'code': 400, 'msg': '当前菜单ID不存在！'})

        if int(status) == 1:
            # 当为目录时，设为顶级父类，parent_id 为 None
            update_query = (
                update(Menu)
                    .where(Menu.id == menu_id)
                    .values(
                    menu_name=menu_name,
                    menu_link=menu_link,
                    menu_icon=menu_icon,
                    menu_order=menu_order,
                    menu_status=menu_status,
                    menu_parent_id=None,
                )
            )
        else:
            # 当为菜单时，设为子菜单，parent_id 为所选父类 ID
            update_query = (
                update(Menu)
                    .where(Menu.id == menu_id)
                    .values(
                    menu_name=menu_name,
                    menu_link=menu_link,
                    menu_icon=menu_icon,
                    menu_order=menu_order,
                    menu_status=menu_status,
                    menu_parent_id=menu_parent_id,
                )
            )

        # 执行更新操作
        db.session.execute(update_query)
        db.session.commit()  # 提交更改

        return jsonify({'code': 200, 'msg': '修改成功！'})

    except Exception as e:
        # 出现错误时回滚事务
        db.session.rollback()
        # 记录错误日志（或直接返回错误信息）
        error_message = f"数据库更新失败: {str(e)}"
        return jsonify({'code': 500, 'msg': error_message})


# 菜单配置添加接口
@menu_view.route('/menu_manage_add', methods=['POST'])
@jwt_required()
@jwt_required_with_refresh
def menu_manage_add():
    """
    菜单配置添加接口

    参数:
        status       状态 (str): 1目录， 2菜单 （选择目录parent_id就为none值，选择菜单，展示对应路径，parent_id有值）
        parent_id    菜单父id (str): 菜单父id。
        menu_id      菜单id (str): 菜单id。
        menu_name    菜单名称 (str): 菜单名称。
        menu_link    菜单路径 (str): 菜单路径。
        menu_order   菜单顺序 (str): 菜单顺序。
        menu_icon    菜单图标 (str): 菜单图标。
    """

    # 先判断状态，当为目录或者菜单时执行不同的逻辑
    status = strip_whitespace(request.form.get('status',None))
    menu_name = strip_whitespace(request.form.get('menu_name',None))
    menu_link = strip_whitespace(request.form.get('menu_link',None))
    menu_order = strip_whitespace(request.form.get('menu_order',None))
    menu_icon = strip_whitespace(request.form.get('menu_icon',None))
    menu_status = strip_whitespace(request.form.get('menu_status',1))
    menu_parent_id = strip_whitespace(request.form.get('menu_parent_id',None))

    # 参数构建判断是否为空
    params = [status, menu_name, menu_order]

    if not all(params):
        return jsonify({'code': 400, 'msg': '设备数据有未填写项'})

    try:

        # 查询菜单名称是否存在，如果已经存在提示
        if  db.session.query(Menu).filter(Menu.menu_name == menu_name).first() is not  None:
            return jsonify({'code': 400, 'msg': '该菜单已经存在'})

        if int(status) == 1:

            # 当为目录时，设为顶级父类，parent_id 为 None
            add_query = Menu(
                    menu_name=menu_name,menu_link=menu_link,
                    menu_icon=menu_icon,menu_order=menu_order,
                    menu_parent_id=None,menu_status=menu_status
            )

        else:
            # 当为菜单时，设为子菜单，parent_id 为所选父类 ID
            add_query = Menu(
                    menu_name=menu_name,menu_link=menu_link,
                    menu_icon=menu_icon,menu_order=menu_order,
                    menu_parent_id=menu_parent_id,menu_status=menu_status
            )

        # 执行添加操作
        db.session.add(add_query)
        db.session.commit()  # 提交更改

        return jsonify({'code': 200, 'msg': '添加成功！'})

    except Exception as e:
        # 出现错误时回滚事务
        db.session.rollback()
        # 记录错误日志（或直接返回错误信息）
        error_message = f"数据库添加失败: {str(e)}"
        return jsonify({'code': 500, 'msg': error_message})


# 菜单状态修改（菜单管理）
@menu_view.route('/menu_manage_status_update', methods=['POST'])
@jwt_required()
@jwt_required_with_refresh
def menu_manage_status_update():
    # 菜单id
    menu_id = request.form.get('menu_id', None)
    # 菜单启用状态  1启用 0禁用
    menu_status = request.form.get('menu_status', 1)
    # 当用户id与用户状态存在
    if menu_id and menu_status:
        # 查询用户相同并且修改状态
        db.session.query(Menu).filter(Menu.id == menu_id).update({'menu_status': menu_status})
        # 数据提交
        db.session.commit()
        return jsonify({'code': 200, 'message': '菜单状态修改成功'})
    return jsonify({'code': 400, 'message': '菜单及状态未输入'})


# 菜单删除（菜单管理）
@menu_view.route('/menu_manage_delete', methods=['POST'])
@jwt_required()
@jwt_required_with_refresh
def menu_manage_delete():
    """
    删除菜单数据

    参数:
        menu_id (str): 要删除的角色ID
    返回:
        json: 响应结果，包含状态码和消息
    """
    # 获取角色ID
    menu_list = request.form.get('menu_list', None)

    # 将字符串转换为列表，确保 menu_list 是 JSON 格式的字符串
    try:
        menu_ids = json.loads(menu_list)
    except json.JSONDecodeError:
        return jsonify({'code': 400, 'message': '无效的菜单列表格式!'})

    # 查找所有匹配的菜单数据
    menus_to_delete = db.session.query(Menu).filter(Menu.id.in_(menu_ids)).all()

    # 如果没有找到任何菜单
    if not menus_to_delete:
        return jsonify({'code': 404, 'message': '菜单不存在!'})

    try:
        # 批量删除菜单
        for menu_data in menus_to_delete:
            db.session.delete(menu_data)

        # 提交事务
        db.session.commit()
        return jsonify({'code': 200, 'message': '菜单删除成功!'})

    except Exception as e:
        # 捕获异常并回滚事务
        db.session.rollback()
        return jsonify({'code': 500, 'message': f'删除菜单时发生错误: {str(e)}'})



# # 对应权限菜单展示接口
# @menu_view.route('/menu_show', methods=['GET'])
# # @jwt_required()
# def menu_show():
#
#     # 获取用户id    在用户权限表里查看关联关系 ，展示对应权限菜单
#     user_id = request.args.get('user_id',None)
#
#     # 判断用户是否存在
#     if not user_id:
#         return jsonify({'code':400,'msg':'用户不存在'})
#
#     # 获取用户权限数据
#     permission_data = db.session.query(UserPermission).filter(UserPermission.user_id==int(user_id)).all()
#     if not permission_data:
#         return jsonify({'code': '400', 'message': '用户不存在'})
#
#     permission_data = convert_folder_to_dict_list(permission_data,['id','user_id','permission_id'])
#     # print(permission_data,'ids')
#
#
#     # 获取用户具有的权限列表（组装为uds 列表）
#     user_permission_ids = eval(list([permission['permission_id'] for permission in permission_data if permission['user_id'] == int(user_id)])[0])
#     # print(user_permission_ids)
#
#     # 查询用户权限对应菜单信息
#     menu_data = db.session.query(Menu).all()
#     menu_data = convert_folder_to_dict_list(menu_data, ['id', 'menu_name', 'menu_link','menu_icon','menu_order','menu_parent_id','menu_permission_list'])
#     # print(menu_data)
#
#     menu_list = []
#     for i in menu_data:
#         i['menu_permission_list'] = eval(i['menu_permission_list'])
#         # 检查用户的权限是否包含菜单的权限要求 如果符合要求将菜单写进新列表
#         if any(permission in user_permission_ids for permission in i['menu_permission_list']):
#             menu_list.append(i)
#
#
#     # 自定义排序函数  按照菜单表自定义顺序来对菜单进行排序
#     def custom_sort(menu):
#         return menu.get('menu_order', 0)
#
#     # 对菜单项列表进行排序
#     sorted_menu_items = sorted(menu_list, key=custom_sort)
#
#     # 从 menu_parent_id为none主节点开始找  （递归找出所有子类菜单）
#     def build_tree(data, parent_id=None):
#         tree = []
#         for item in data:
#             if item['menu_parent_id'] == parent_id:
#                 children = build_tree(data, item['id'])
#                 if children:
#                     item['children'] = children
#                 tree.append(item)
#         return tree
#
#     # 调用方法获取父子菜单组装数据
#     menu_list = build_tree(sorted_menu_items)
#
#     print(menu_list)
#     return jsonify({'code': 200, 'menu_list': menu_list})


